package dk.viauc.friendlocator;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import android.location.Criteria;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class MainActivity extends FragmentActivity {

	// Class variables
	Marker m;
	GoogleMap map;
	ArrayList<FriendLocation> list;
	FriendLocation me;
	LocationManager locManager;
	Criteria crit;
	LocationListenerImpl locListener;

	private Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			android.location.Location loc = (android.location.Location) msg.obj;
			FriendLocation l = new FriendLocation(Globals.NAME, new LatLng(
					loc.getLatitude(), loc.getLongitude()),
					(String) DateFormat.format("dd MMMM yyyy, kk:mm",
							loc.getTime()));
			me = l;
			updateLocation(l);
			if (!list.isEmpty()) {
				showFriends();
				centerCamera();
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_main);

		// set up the list of friends
		list = new ArrayList<FriendLocation>();

		// initialize the map
		map = ((SupportMapFragment) getSupportFragmentManager()
				.findFragmentById(R.id.fragment1)).getMap();
		map.setMyLocationEnabled(true);

		Button refresh = (Button) findViewById(R.id.button1);
		refresh.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				locManager.requestSingleUpdate(crit, locListener, null);

				if (me != null)
					updateLocation(me);
			}
		});

		crit = new Criteria();
		crit.setAccuracy(Criteria.ACCURACY_FINE);
		crit.setPowerRequirement(Criteria.POWER_HIGH);
		crit.setAltitudeRequired(false);
		crit.setBearingRequired(false);
		crit.setSpeedRequired(false);
		crit.setCostAllowed(true);
		
		locListener = new LocationListenerImpl(handler);
		locManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		if (locManager.getBestProvider(crit, true).isEmpty())
			Toast.makeText(this, "Please enable GPS or Network Location",
					Toast.LENGTH_LONG).show();
		else
			locManager.requestLocationUpdates(Globals.GPS_REFRESH_TIME,
					Globals.GPS_REFRESH_DISTANCE, crit, locListener, null);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public void centerCamera() {
		if (list.size() == 1) {
			// If there's only one marker, then just center it on the map
			CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(list.get(0)
					.getLocation(), 15f);
			map.animateCamera(cu);
		}
		else {
			// Otherwise build bounds which display all the markers
			LatLngBounds.Builder builder = new LatLngBounds.Builder();
			for (FriendLocation fl : list) {
				if (fl.getMarker() != null)
					builder.include(fl.getMarker().getPosition());
			}

			LatLngBounds bounds = builder.build();
			CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 100);
			map.animateCamera(cu);
		}

	}

	private void updateLocation(FriendLocation loc) {
		FriendLocation[] frLoc = { loc };
		WebServiceUpdate update = new WebServiceUpdate(this);
		update.execute(frLoc);
		try {
			ArrayList<FriendLocation> updateList = update.get();
			outerloop: for (FriendLocation newFl : updateList) {
				for (FriendLocation oldFl : list)
					if (oldFl.getName().equals(newFl.getName())) {
						oldFl.setLocation(newFl.getLocation());
						oldFl.setMarker(null);
						oldFl.setDate(newFl.getDate());
						continue outerloop;
					}
				list.add(newFl);
			}
		}
		catch (InterruptedException e) {
			Log.e(getLocalClassName(), "Location update failed", e);
			Toast.makeText(this, "Update location failed", Toast.LENGTH_LONG)
					.show();
		}
		catch (ExecutionException e) {
			Log.e(getLocalClassName(), "Location update failed", e);
		}
	}

	private void showFriends() {
		map.clear();
		for (FriendLocation fl : list)
			if (fl.getMarker() == null) {
				fl.setMarker(map.addMarker(new MarkerOptions()
						.position(fl.getLocation()).title(fl.getName())
						.snippet("Updated: " + fl.getDate())));
				fl.getMarker().showInfoWindow();
			}
			else {
				map.addMarker(new MarkerOptions().position(fl.getLocation())
						.title(fl.getName())
						.snippet("Updated: " + fl.getDate()));
				fl.getMarker().showInfoWindow();
			}
	}
}